package com.lsh.oms.worker.service.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dangdang.ddframe.job.api.JobExecutionMultipleShardingContext;
import com.dangdang.ddframe.job.plugin.job.type.simple.AbstractSimpleElasticJob;
import com.lsh.base.trace.id.filter.TraceIdSetter;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.enums.PayStatus;
import com.lsh.oms.core.enums.PayType;
import com.lsh.oms.core.enums.TaskStatus;
import com.lsh.oms.core.enums.TaskType;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.email.EmailModel;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.model.payment.BillPaymentInfo;
import com.lsh.oms.core.model.po.OmsTask;
import com.lsh.oms.core.proxy.service.RefundProxy;
import com.lsh.oms.core.records.core.ReturnRepository;
import com.lsh.oms.core.service.asynservice.OmsEventBus;
import com.lsh.oms.core.service.order.OrderQueryService;
import com.lsh.oms.core.service.payment.BillPaymentService;
import com.lsh.oms.core.service.payment.PaymentService;
import com.lsh.oms.core.service.po.OmsTaskService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
 * Project Name: OrderRefundTask
 * 北京链商电子商务有限公司
 * Auth: wangliutao
 * Date: 18/6/7
 * Package Name: com.lsh.oms.worker.service.task
 * Description:功能描述:
 * 定时扫描omsTask表,向商城提交退款申请
 */
@Component
public class OrderRefundTask extends AbstractSimpleElasticJob {

    private static final Logger logger = LoggerFactory.getLogger(OrderRefundTask.class);
    private static final String CANCEL_TYPE = "type";

    @Autowired
    private OmsTaskService omsTaskService;

    @Autowired
    private RefundProxy refundProxy;

    @Autowired
    private OrderQueryService orderQueryService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private BillPaymentService billPaymentService;

    @Resource
    private ReturnRepository returns;

    @Value("${run.system}")
    private String system;

    @Override
    public void process(JobExecutionMultipleShardingContext shardingContext) {
        TraceIdSetter.set();
        logger.info("[order refund task] fetch data [start]");
        List<OmsTask> tasks = omsTaskService.getTasksByTypeAndStatuses(TaskType.REFUND.getCode(), Arrays.asList(TaskStatus.TASK_UN_DEAL.getCode()), 10);

        if (tasks == null) {
            return;
        }
        logger.info("[order refund task] fetch data [end]! size: {}", tasks.size());

        for (OmsTask task : tasks) {
            logger.info("[order refund task] process task: {}", JSON.toJSONString(task));

            Long orderCode = Long.valueOf(task.getRefCode());
            try {
                OrderHead orderHead = orderQueryService.findByCode(orderCode, false, false);
                // 校验参数
                if (orderHead == null) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "查询不到该订单, 订单号: " + orderCode);
                }
                this.validationOrderStatus(orderHead);
                // 组合参数,请求商城退款接口
                JSONObject ext = JSON.parseObject(task.getExt());
                if (ext == null) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "task's ext is null, 订单号: " + orderCode);
                }

                // 如果是全单捡缺，需要通知商城退券
                Boolean needNotifyRefundCoupon = ext.getBoolean("coupon");
                if (needNotifyRefundCoupon != null && needNotifyRefundCoupon) {
                    this.paymentService.orderCancelNotifyShop(Collections.singletonList(orderCode), "[order refund task]", orderHead.getVenderId());
                }

                OmsTask taskForUpdate = new OmsTask();
                taskForUpdate.setId(task.getId());
                taskForUpdate.setExecCount(task.getExecCount());
//                if (PayType.PAY_ON_DELIVERY.getValue().equals(orderHead.getPayType())) {
//                    logger.info("[order refund task] 订单是货到付款，不需要请求退款");
//                    taskForUpdate.setTaskStatus(TaskStatus.TASK_DEAL_SUCCESS.getCode());
//                } else {
                JSONObject responseJson = this.refundProxy.refund(orderCode, ext.getInteger(CANCEL_TYPE), orderHead.getVenderId(), new HashMap<>());
                logger.info("[order refund task] request refund response: {}", responseJson);
                if (responseJson == null) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "request refund failed !, 订单号: " + orderCode);
                }
                String ret = responseJson.getString("ret");

                // 更新omsTask
                logger.info("[order refund task] update omsTask! start");

                if (ret.equals("0")) {
                    taskForUpdate.setTaskStatus(TaskStatus.TASK_DEAL_SUCCESS.getCode());
                } else {
                    String msg = responseJson.getString("msg");
                    taskForUpdate.setTaskStatus(TaskStatus.TASK_DEAL_FAIL.getCode());
                    taskForUpdate.setContent(msg);
                    this.sendEmail(msg, task); //邮件报警
                    logger.info("[order refund task] request refund failed! ret: {}, msg: {}", ret, responseJson.getString("msg"));
                }

//                }
                omsTaskService.updateTaskAndAddExecCount(taskForUpdate);

                logger.info("[order refund task] update omsTask! end");
            } catch (BusinessException e) {
                logger.error("[order refund task] process failed! msg: " + e.getMessage(), e);
                // 更新omsTask
                OmsTask taskForUpdate = new OmsTask();
                taskForUpdate.setId(task.getId());
                taskForUpdate.setTaskStatus(TaskStatus.TASK_DEAL_FAIL.getCode());
                taskForUpdate.setExecCount(task.getExecCount());
                omsTaskService.updateTaskAndAddExecCount(taskForUpdate);
                this.sendEmail(e.getMessage(), task); //邮件报警
            } catch (Exception e) {
                logger.error("[order refund task] error! msg: " + e.getMessage(), e);
            }
            logger.info("[order refund task] process task end!");
        }
    }

    private void validationOrderStatus(OrderHead head) {
        Long orderCode = head.getOrderCode();
        // 判断订单的支付类型,是否是在线支付
//        if (PayType.PAY_ON_DELIVERY.getValue().equals(head.getPayType())) {
//            throw new BusinessException(ReturnCode.REQUEST_FAIL, "订单支付类型:货到付款, 订单号: " + orderCode);
//        }

        // 判断订单的支付状态,是否是已支付
        if (!PayType.PAY_ON_DELIVERY.getValue().equals(head.getPayType())) {
            if (!PayStatus.PAID.getValue().equals(head.getPayStatus())) {
//            throw new BusinessException(ReturnCode.REQUEST_FAIL, "订单未支付, 订单号: " + orderCode);
                BillPaymentInfo payFilter = new BillPaymentInfo();
                payFilter.setBillCode(orderCode);
                payFilter.setPayStatus(PayStatus.PAID.getValue());
                payFilter.setIsValid(1);
                Integer count = billPaymentService.countByFilter(payFilter);
                if (count == null || count.intValue() == 0) {
                    logger.info("[预付--退款] 订单没有支付成功的记录, orderCode: {}", orderCode);
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "该订单没有支付成功的记录, 订单号: " + orderCode);
                }
            }
        }
    }

    private void sendEmail(String msg, OmsTask task) {
        // 邮件报警
        String title = "[" + system + "][oms-OrderRefundTask]";
        String[] persons = {"wangliutao@lsh123.com"};

        StringBuilder sb = new StringBuilder("【警告】订单终态,通知商城失败!!");
        sb.append("\n").append("refCode: ").append(task.getRefCode())
                .append("\n").append("taskType: ").append(task.getTaskType()).append("\n")
                .append("message: ").append(msg);

        OmsEventBus.post(new EmailModel(sb.toString(), title, persons));
    }

}
